﻿/*
 * This software is the confidential and proprietary
 * information of NetBay
 * Such confidential information should not be disclosed
 * NetBay copyright(c) 2010
 */

#region Using
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.ServiceModel.DomainServices.Server;
using NetBay.Core.BusinessEntities;
using NetBay.Core.Log;
using Rio.Applications.Web.RioWCFServices;
using Rio.Framework.RioManager;
using System.Linq;
using System.Text.RegularExpressions;
using NetBay.Core.Extensions;
#endregion

namespace Rio.Applications.Web.Services 
{
    /// <summary>
    /// Class to handle Business entities in a RIA services
    /// </summary>
    public partial class BusinessEntitiesDomainService : DomainService
    {
        #region Publics

        /// <summary>
        /// 
        /// </summary>
        /// <param name="P_szPathStorageSource"></param>
        /// <param name="P_swDirectory"></param>
        /// <param name="P_lswFiles">Repertory and subdirectory P_swDirectory 's files</param>
        public void ListDirectoryFiles(string P_szPathStorageSource, string P_swDirectory, ref List<Vignette> P_lswFiles)
        {
            DirectoryInfo L_diDirectory = new DirectoryInfo(P_swDirectory);

            if (L_diDirectory.Exists)
            {
                try
                {
                    foreach (string d in Directory.GetDirectories(P_swDirectory))
                        ListDirectoryFiles(P_szPathStorageSource, d, ref P_lswFiles);
                }
                catch (UnauthorizedAccessException) { }
                foreach (string file in Directory.GetFiles(P_swDirectory))
                {
                    Bitmap L_bmpImage = new Bitmap(file);
                    MemoryStream ms = new MemoryStream();

                    L_bmpImage.Save(ms, ImageFormat.Png);

                    P_lswFiles.Add(new Vignette(P_szPathStorageSource, file, ms.ToArray()));
                }
            }
        }
        #endregion

        #region Queries
        /// <summary>
        /// Return the image in RioDoc which correspond at the path file parameter
        /// </summary>    
        [Query(HasSideEffects=true)]
        public IEnumerable<ImageRio> GetImageRioDocVignette(IEnumerable<string> P_oPathFile)
        {
            List<ImageRio> L_oListImageRio = new List<ImageRio>();
            string L_szFolder = SettingsManager.cStoreSettings.Thumbnail_Directory;

            FileInfo L_oFile = null;
            FileStream L_fsfileStream = null;
            byte[] l_obuffer = null;

            foreach (string path in P_oPathFile)
            {
                L_oFile = new FileInfo(L_szFolder + @"\" + path + NetBay.Core.BusinessEntities.Constant.ImageFileFormat.JPG.szGetDescription());

                if (L_oFile.Exists)
                {
                    try
                    {
                        L_fsfileStream = L_oFile.OpenRead();
                        l_obuffer = new byte[L_fsfileStream.Length];
                        L_fsfileStream.Read(l_obuffer, 0, (int)L_fsfileStream.Length);
                        L_fsfileStream.Close();

                        L_oListImageRio.Add(new ImageRio(L_oFile.FullName.Substring(L_szFolder.Length, L_oFile.FullName.Length - L_szFolder.Length), l_obuffer));
                    }
                    catch (Exception ex)
                    {
                        ImageRio l_oImageRioError = new ImageRio("()", ex);
                        NetBay.Core.Log.LogManager.Instance().LogError(l_oImageRioError.FullErrorMessage);
                        L_oListImageRio.Add(l_oImageRioError);
                    }
                }
            }

            return L_oListImageRio;
        }

        private ReturnObject SaveRotateFile(string P_sFileName, int P_oRotateFlip)
        {
            // Initialization
            ReturnObject l_oReturnObject = new ReturnObject();
            string l_sImageFileName = P_sFileName;
            byte[] l_oBitArray = null;
            FileInfo l_oCurrentFileInfo = null;
            Image l_oImage = null;
            MemoryStream L_oMSImage = new MemoryStream();
            string L_szFolder = SettingsManager.cStoreSettings.Parameter_Storage;

            try
            {
                #region Rotating and saving source file
                //Getting source file informations
                l_oCurrentFileInfo = new FileInfo(L_szFolder + l_sImageFileName);
                FileStream L_oImageStream = l_oCurrentFileInfo.OpenRead();
                l_oImage = Image.FromStream(L_oImageStream);
                L_oImageStream.Dispose();
                   
                RotateFlipType L_oCurrentRotateFlip = RotateFlipType.RotateNoneFlipNone;

                switch (P_oRotateFlip)
                {
                    case 0:
                        L_oCurrentRotateFlip = RotateFlipType.RotateNoneFlipNone;
                        break;
                    case 90:
                        L_oCurrentRotateFlip = RotateFlipType.Rotate90FlipNone;
                        break;
                    case 180:
                        L_oCurrentRotateFlip = RotateFlipType.Rotate180FlipNone;
                        break;
                    case 270:
                        L_oCurrentRotateFlip = RotateFlipType.Rotate270FlipNone;
                        break;
                    default:
                        break;
                }

                l_oImage.RotateFlip(L_oCurrentRotateFlip);

                if (l_oCurrentFileInfo.Extension.ToLower().Equals(NetBay.Core.BusinessEntities.Constant.ImageFileFormat.JPEG.szGetDescription()) || l_oCurrentFileInfo.Extension.ToLower().Equals(NetBay.Core.BusinessEntities.Constant.ImageFileFormat.JPG.szGetDescription()))
                    l_oImage.Save(L_oMSImage, ImageFormat.Jpeg);
                else if (l_oCurrentFileInfo.Extension.ToLower().Equals(NetBay.Core.BusinessEntities.Constant.ImageFileFormat.BMP.szGetDescription()))
                    l_oImage.Save(L_oMSImage, ImageFormat.Bmp);
                else if (l_oCurrentFileInfo.Extension.ToLower().Equals(NetBay.Core.BusinessEntities.Constant.ImageFileFormat.PNG.szGetDescription()))
                    l_oImage.Save(L_oMSImage, ImageFormat.Png);
                else if (l_oCurrentFileInfo.Extension.ToLower().Equals(NetBay.Core.BusinessEntities.Constant.ImageFileFormat.TIF.szGetDescription()) || l_oCurrentFileInfo.Extension.ToLower().Equals(NetBay.Core.BusinessEntities.Constant.ImageFileFormat.TIFF.szGetDescription()))
                    l_oImage.Save(L_oMSImage, ImageFormat.Tiff);
                else if (l_oCurrentFileInfo.Extension.ToLower().Equals(NetBay.Core.BusinessEntities.Constant.ImageFileFormat.GIF.szGetDescription()))
                    l_oImage.Save(L_oMSImage, ImageFormat.Gif);
                else
                {
                    l_oReturnObject = new ReturnObject("Format not supported");
                    NetBay.Core.Log.LogManager.Instance().LogError("Format not supported");
                    return l_oReturnObject;
                }

                    

                l_oBitArray = L_oMSImage.ToArray();
                L_oMSImage.Dispose();
                using (Stream s = File.Create(l_oCurrentFileInfo.FullName))
                {
                    s.Write(l_oBitArray, 0, l_oBitArray.Length);
                }
                l_oImage.Dispose();

                #endregion

                return l_oReturnObject;
            }
            catch (Exception ex)
            {
                l_oReturnObject = new ReturnObject(ex.Message);
                NetBay.Core.Log.LogManager.Instance().LogError(ex.Message);
                return l_oReturnObject;
            }
                        
        }

        /// <summary>
        /// Rotate and save
        /// </summary>
        /// <param name="p_lsImagesToRotateAndSave">List of fileName and associated rotation to apply</param>
        [Query(HasSideEffects=true)]
        public IEnumerable<ReturnObject> SaveRotatedImages(Dictionary<string, string> p_lsImagesToRotateAndSave)
        {
            List<ReturnObject> l_oReturnObjects = new List<ReturnObject>();

            try
            {
                // Initialization
                byte[] l_oBitArray = null;
                FileInfo l_oCurrentFileInfo = null;
                Image l_oImage = null;
                Image l_oFirstImage = null;
                Image l_oImageNext = null;
                MemoryStream ms = new MemoryStream();
                FileStream L_oImageStream;
                RotateFlipType L_oCurrentRotateFlip = RotateFlipType.RotateNoneFlipNone;
                RotateFlipType L_oFirstRotateFlip = RotateFlipType.RotateNoneFlipNone;

                string L_szFolder = SettingsManager.cStoreSettings.Parameter_Storage;

                foreach (string l_sImageFileName in p_lsImagesToRotateAndSave.Keys)
                {
                    #region Rotating and saving source file

                    Regex L_oRegx = new Regex(@"(\d+)#(\d+);");
                    MatchCollection L_oMatches = L_oRegx.Matches(p_lsImagesToRotateAndSave[l_sImageFileName]);

                    if (L_oMatches.Count == 1)
                    {
                        l_oReturnObjects.Add(SaveRotateFile(l_sImageFileName, Convert.ToInt32(L_oMatches[0].Groups[2].Value)));
                        switch (L_oMatches[0].Groups[2].Value)
                        {
                            case "0":
                                L_oFirstRotateFlip = RotateFlipType.RotateNoneFlipNone;
                                break;
                            case "90":
                                L_oFirstRotateFlip = RotateFlipType.Rotate90FlipNone;
                                break;
                            case "180":
                                L_oFirstRotateFlip = RotateFlipType.Rotate180FlipNone;
                                break;
                            case "270":
                                L_oFirstRotateFlip = RotateFlipType.Rotate270FlipNone;
                                break;
                            default:
                                break;
                        }
                    }
                    else
                    {
                        //Getting source file informations
                        l_oCurrentFileInfo = new FileInfo(L_szFolder + l_sImageFileName);
                        L_oImageStream = l_oCurrentFileInfo.OpenRead();
                        l_oImage = Image.FromStream(L_oImageStream);
                        Guid L_oTempGuid = Guid.NewGuid();
                        string L_oTempFilePath = System.IO.Path.Combine(l_oCurrentFileInfo.DirectoryName, L_oTempGuid.ToString()) + NetBay.Core.BusinessEntities.Constant.ImageFileFormat.TIF.szGetDescription();
                        
                        //get ImageCodecInfo, generate tif format
                        ImageCodecInfo info = null;
                        foreach (ImageCodecInfo ice in ImageCodecInfo.GetImageEncoders())
                        {
                            if (ice.MimeType == "image/tiff")
                            {
                                info = ice;
                                break;
                            }
                        }
                        //define the encoderparameter,
                        //when the 1st page, will be EncoderValue.MultiFrame.
                        //when the other pages, will be EncoderValue.FrameDimensionPage.
                        //when all pages saved, will be the EncoderValue.Flush.	 */
                        EncoderParameters ep = new EncoderParameters(2);
                        

                        for (int i = 0; i < L_oMatches.Count; i++)
                        {

                            switch (L_oMatches[i].Groups[2].Value)
                            {
                                case "0":
                                    L_oCurrentRotateFlip = RotateFlipType.RotateNoneFlipNone;
                                    break;
                                case "90":
                                    L_oCurrentRotateFlip = RotateFlipType.Rotate90FlipNone;
                                    break;
                                case "180":
                                    L_oCurrentRotateFlip = RotateFlipType.Rotate180FlipNone;
                                    break;
                                case "270":
                                    L_oCurrentRotateFlip = RotateFlipType.Rotate270FlipNone;
                                    break;
                                default:
                                    break;
                            }

                            l_oImage.SelectActiveFrame(FrameDimension.Page, Convert.ToInt32(L_oMatches[i].Groups[1].Value));
                            
                            l_oImage.Save(ms, ImageFormat.Tiff);
                            l_oImageNext = Image.FromStream(ms);

                            if (l_oImageNext.PixelFormat == PixelFormat.Format1bppIndexed)
                            {
                                ep.Param[0] = new EncoderParameter(Encoder.Compression, Convert.ToInt32(EncoderValue.CompressionCCITT4));
                            }
                            else
                            {
                                ep.Param[0] = new EncoderParameter(Encoder.Compression, Convert.ToInt32(EncoderValue.CompressionLZW));
                            }

                            l_oImageNext.RotateFlip(L_oCurrentRotateFlip);

                            if (Convert.ToInt32(L_oMatches[i].Groups[1].Value) == 0)
                            {
                                L_oFirstRotateFlip = L_oCurrentRotateFlip;
                                l_oFirstImage = l_oImageNext;

                                
                                ep.Param[1] = new EncoderParameter(Encoder.SaveFlag, Convert.ToInt32(EncoderValue.MultiFrame));
                                l_oFirstImage.Save(L_oTempFilePath, info, ep);
                            }
                            else
                            {
                                ep.Param[1] = new EncoderParameter(Encoder.SaveFlag, Convert.ToInt32(EncoderValue.FrameDimensionPage));
                                l_oFirstImage.SaveAdd(l_oImageNext, ep);
                            }


                        }

                        ep.Param[1] = new EncoderParameter(Encoder.SaveFlag, Convert.ToInt32(EncoderValue.Flush));
                        l_oFirstImage.SaveAdd(ep);

                        l_oImageNext.Dispose();
                        L_oImageStream.Dispose();
                        l_oImage.Dispose();

                        l_oFirstImage.Dispose();
                        File.Delete(l_oCurrentFileInfo.FullName);
                        File.Move(L_oTempFilePath, l_oCurrentFileInfo.FullName);

                        // Delete temp thumb created before
                        FileInfo l_oTempThumbFileInfo = new FileInfo(SettingsManager.cStoreSettings.Thumbnail_Directory + @"\" + L_oTempGuid.ToString() + NetBay.Core.BusinessEntities.Constant.ImageFileFormat.TIF.szGetDescription() + NetBay.Core.BusinessEntities.Constant.ImageFileFormat.JPG.szGetDescription());
                        File.Delete(l_oTempThumbFileInfo.FullName);
                    }

                    #endregion

                    #region Rotating and saving thumb file

                    //Getting source file informations
                    string L_szFolderThumbs = SettingsManager.cStoreSettings.Thumbnail_Directory;
                    l_oCurrentFileInfo = new FileInfo(L_szFolderThumbs + @"\" + l_sImageFileName + NetBay.Core.BusinessEntities.Constant.ImageFileFormat.JPG.szGetDescription());
                    
                    L_oImageStream = l_oCurrentFileInfo.OpenRead();
                    l_oImage = Image.FromStream(L_oImageStream);
                    L_oImageStream.Dispose();

                    l_oImage.RotateFlip(L_oFirstRotateFlip);

                    ms = new MemoryStream();
                    l_oImage.Save(ms, ImageFormat.Jpeg);

                    l_oBitArray = ms.ToArray();
                    ms.Dispose();

                    using (Stream s = File.Create(l_oCurrentFileInfo.FullName))
                    {
                        s.Write(l_oBitArray, 0, l_oBitArray.Length);
                    }
                    l_oImage.Dispose();

                    #endregion
                }


            }
            catch (Exception ex)
            {
                ReturnObject l_oReturnObject = new ReturnObject(ex.Message);
                NetBay.Core.Log.LogManager.Instance().LogError(ex.Message);
                l_oReturnObjects.Add(l_oReturnObject);
            }
            return l_oReturnObjects;
            
        }

        /// <summary>
        /// Return the image in RioDoc which correspond at the path file parameter
        /// </summary>    
        [Query(HasSideEffects=true)]
        public IEnumerable<ReturnByte> ConvertDocumentToRasterImage(byte[] p_oDoc)
        {

            List<ReturnByte> _ret = new List<ReturnByte>();
            //RasterCodecs.Startup();
            //RasterCodecs _codec;
            //_codec = new RasterCodecs();

            //MemoryStream _stream = new MemoryStream(p_oDoc);
            //MemoryStream _streamOut =  null;

            //RasterImageFormat _format = RasterImageFormat.Tif;
            ////CodecsSavePageMode _pageMode = CodecsSavePageMode.Append;
            //_codec.Options.Pdf.Load.XResolution = 200;
            //_codec.Options.Pdf.Load.YResolution = 200;

            //RasterImage image = _codec.Load(_stream);

            //_codec.Save(image,
            //         _streamOut,
            //         _format,
            //         24
            //         );
            //RasterCodecs.Shutdown();
            ReturnByte oo = new ReturnByte();
            //oo.Value = _streamOut.ToArray();
            _ret.Add(oo);

            return _ret;

        }

        /// <summary>
        /// Return the image in RioDoc which correspond at the path file parameter
        /// </summary>    
        //[Query(HasSideEffects=true)]
        //public IEnumerable<ReturnObject> MergeDocumentsInPDFForPrint(long p_lUserId, string[] p_aSelectedFileName)
        //{
        //    List<ReturnObject> L_oListRet = new List<ReturnObject>();
        //    string L_szFolder = SettingsManager.cStoreSettings.Parameter_Storage;

        //    try
        //    {
        //        // Call the WCF services to build the PDF file and retreive the fullPath to access it
        //        WCFServiceClient l_oWCFRioServices = new WCFServiceClient();
        //        MergeImportDocumentInPdfResponse l_oResponse = l_oWCFRioServices.MergeImportDocumentInPdf(new MergeImportDocumentInPdfRequest(p_aSelectedFileName, p_lUserId,false));
        //        ReturnString l_oReturn = l_oResponse.MergeImportDocumentInPdfResult;
        //        if (l_oReturn.IsValid == false)
        //        {
        //            throw new Exception("Unable to merge in PDF the selected files");
        //        }
        //    }
        //    catch (Exception ex)
        //    {
        //        ReturnObject l_oReturn = new ReturnObject("(p_lUserId<" + p_lUserId + "> p_aSelectedFileName<" + p_aSelectedFileName.ToString(";") + ">)", ex);
        //        NetBay.Core.Log.LogManager.Instance().LogError(l_oReturn.FullErrorMessage);
        //        L_oListRet.Add(l_oReturn);
        //    }

        //    return L_oListRet;
        //}
        #endregion

        #region Invoke
        /// <summary>
        /// Return the number of page of tiff file
        /// </summary>    
        [Invoke(HasSideEffects = true)]
        public int GetCountTiffPage(string P_oPathFile)
        {
            string L_szFolder = SettingsManager.cStoreSettings.Parameter_Storage;
            FileInfo l_oCurrentFileInfo = new FileInfo(L_szFolder + @"\" + P_oPathFile);
            FileStream L_oImageStream = l_oCurrentFileInfo.OpenRead();
            Image l_oImage = Image.FromStream(L_oImageStream);
            L_oImageStream.Dispose();
            return l_oImage.GetFrameCount(FrameDimension.Page);
        }
        #endregion

    }
}